﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Golos.Helper;

namespace Golos.Tags.TagCache
{
    public partial class Cache
    {
        public Cache()
        {
            tags = new TagsDictionary();
            questionTags = new QuestionTagsDictionary();
            UpCache();
        }

        private void UpCache()
        {
            LogClass.WriteInfoEntry("Start UpCache");
            lock (tags)
            {
                GetTagCacheFromDb();

            }
            LogClass.WriteInfoEntry(string.Format("End UpCache tags.count={0}", tags.Count));
        }

        public void AddTags(Guid questionId, List<string> newTags)
        {
            lock (tags)
            {
                foreach (string newTag in newTags)
                {
                    if(!tags.ContainsKey(newTag))
                    {
                        if(!SaveNewTagInDb(questionId, newTag, true))
                            throw new Exception("Can't save tag in db");
                        tags.Add(newTag, new List<Guid>());
                        tags[newTag].Add(questionId);
                    }
                    else
                    {
                        if (tags.Get(newTag).Contains(questionId))
                            continue;
                        if (!SaveNewTagInDb(questionId, newTag, false))
                            throw new Exception("Can't save tag in db");
                        tags[newTag].Add(questionId);
                    }
                    lock (questionTags)
                    {
                        if (!questionTags.ContainsKey(questionId))
                            questionTags.Add(questionId, new List<string>());
                        if (!questionTags.ContainsValue(questionId, newTag))
                            questionTags[questionId].Add(newTag);
                    }
                }
            }
            
        }

        public List<Guid> GetQuestionIds(string tag)
        {
            lock (tags)
            {
                return tags.Get(tag);
            }
        }

        public List<string> GetQuestionTags(Guid questionId)
        {
            lock (questionTags)
            {
                if(!questionTags.ContainsKey(questionId))
                    return new List<string>();
                return questionTags[questionId];
            }
        }

        public List<string> GetAllTags()
        {
            lock (tags)
            {
                List<string> result = new List<string>();
                foreach (string tag in tags.Keys)
                {
                    if(tags[tag].Count>0)
                        result.Add(tag);
                }
                return result;
            }
        }

        public List<string> GetPopularTags()
        {
            SortedDictionary<int, string> popularTags = new SortedDictionary<int, string>();
            lock (tags)
            {
                if (tags.Count == 0)
                    return new List<string>();
                foreach (string tag in tags.Keys)
                {
                    if (tags[tag].Count == 0)
                        continue;
                    if (!popularTags.ContainsKey(tags[tag].Count))
                        popularTags.Add(tags[tag].Count, tag);
                    else
                        popularTags[tags[tag].Count] += string.Format(";{0}", tag);
                }
            }
            List<string> result = new List<string>();
            int max = 24;
            foreach (var keyValuePair in popularTags.Reverse())
            {
                if (max == 0)
                    break;
                result.Add(string.Format("{0}:{1}", keyValuePair.Value, keyValuePair.Key));
                max--;
            }
            return result;
        }

        public void RemoveQuestionTags(Guid questionId)
        {
            if (!RemoveQuestionTagsInDb(questionId))
                throw new Exception("Can't remove question tags in db");
            lock (questionTags)
            {
                if (!questionTags.ContainsKey(questionId))
                    questionTags.Remove(questionId);
            }
            lock (tags)
            {
                foreach (var tag in tags.Keys)
                {
                    if (tags[tag].Contains(questionId))
                        tags[tag].Remove(questionId);
                }
            }

        }

        private readonly TagsDictionary tags;
        private readonly QuestionTagsDictionary questionTags;


        
    }

    
}
